package server

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"gitlab.local/DO-module/new-filemanage-module/server/auth"
	"gitlab.local/DO-module/new-filemanage-module/server/pubsub"
	"gitlab.local/DO-module/new-filemanage-module/src/controller"
	"gitlab.local/DO-module/new-filemanage-module/src/core/fileoperate"
	"gitlab.local/DO-module/new-filemanage-module/src/core/httplogger"

	"gitlab.local/DO-module/acl-module/src/service/acl"
	"gitlab.local/DO-module/new-filemanage-module/src/core/middleware"
	database "gitlab.local/DO-module/new-filemanage-module/src/core/sqlitedb"
	"gitlab.local/DO-module/new-filemanage-module/src/service/filesystem"
	"gitlab.local/DO-module/new-filemanage-module/src/service/folder"
	//"gitlab.local/TerraMaster/tos-modules/middleware"
	sharefolder2 "gitlab.local/TerraMaster/tos-modules/service/sharefolder"
	"log/slog"
	"net"
	"net/http"
	"os"
)

type Server struct {
	httpServer    *http.Server
	logger        *slog.Logger
	upgrader      *websocket.Upgrader
	pubsub        *pubsub.PubSub
	sockPath      string
	authenticator auth.Authenticator
	fs            *filesystem.FileSystem
}

type WebSocketHandler func(msg []byte) (interface{}, error)

func New(logger *slog.Logger, muxs *gin.Engine, opts ...Option) *Server {
	s := Server{
		httpServer: &http.Server{Addr: ":8383", Handler: muxs},
		logger:     logger,
		upgrader: &websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool { return true },
		},
	}

	for _, opt := range opts {
		opt.Config(&s)
	}

	if len(s.sockPath) == 0 {
		s.sockPath = "/run/file-manage.sock"
	}

	/*if s.authenticator == nil {
		s.authenticator = &auth.AnonymousAuthenticator{}
	}
	if s.pubsub == nil {
		s.pubsub = pubsub.New(logger)
	}*/
	//s.httpServer.Handler = s.createRouter(muxs)
	logger.Info("start ...")
	return &s
}

func (s *Server) CreateRouter(engine *gin.Engine,
	checker middleware.AuthChecker,
	dbGetter database.Getter,
	shareGetter fileoperate.Getter,
	aclGetter acl.FolderAttrService,
	fs *filesystem.FileSystem,
	folders *folder.Folder,
	shareFolder sharefolder2.Service,
) {

	controller.FileSystemRouter(engine, checker, shareGetter, aclGetter, fs, folders)
	shareF := controller.ShareFolder{}
	shareF.Router(httplogger.New(), engine, checker, shareFolder, folders)

	// 注册普通 HTTP 路由
	//router.HandleFunc("/fileManage", s.handleTest)
	//FileSystemRouter
	// 注册 WebSocket 路由
	//router.HandleFunc("/fileManage/websocket/{subroute}", authMiddleware(http.HandlerFunc(s.handleWebSocket)))

	//return router
}

func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
	subroute := mux.Vars(r)["subroute"]
	handler, ok := s.getWebSocketHandler(subroute)
	if !ok {
		http.NotFound(w, r)
		return
	}

	// Upgrade HTTP connection to WebSocket
	ws, err := s.upgrader.Upgrade(w, r, nil)
	if err != nil {
		http.Error(w, "Failed to upgrade to WebSocket", http.StatusInternalServerError)
		return
	}
	defer ws.Close()

	for {
		_, msg, err := ws.ReadMessage()
		if err != nil {
			// Handle read error or WebSocket connection closed
			break
		}
		//fmt.Println(msg)
		// Handle received message
		s.logger.Info("Received message:", "message", string(msg))

		// Process the received message
		res, err := handler(msg)
		data, _ := json.Marshal(res)
		// Write response message
		responseMsg := []byte("Server received: " + string(data))
		err = ws.WriteMessage(websocket.TextMessage, responseMsg)
		if err != nil {
			// Handle write error
			break
		}
	}

	// Handle WebSocket events (read/write/close)

}

func (s *Server) getWebSocketHandler(subroute string) (WebSocketHandler, bool) {
	// 根据子路由名称返回相应的 WebSocket 处理函数
	/*subrouteHandlers := map[string]WebSocketHandler{
		"GetShareStatus": s.fs.HandleFileDownload,
	}
	if _, ok := subrouteHandlers[subroute]; ok {
		return subrouteHandlers[subroute], true
	}*/
	return nil, false
}

func (s *Server) _Run() error {

	if l, err := net.Dial("unix", s.sockPath); err == nil {
		l.Close()
		return fmt.Errorf("sock %s is already in used", s.sockPath)
	}
	_ = os.Remove(s.sockPath)
	l, err := net.Listen("unix", s.sockPath)
	if err != nil {
		return err
	}
	s.logger.Info("listening on IPC socket", "path", s.sockPath)
	return s.httpServer.Serve(l)
}

func (s *Server) Run() error {
	listener, err := net.Listen("tcp", ":8383")
	if err != nil {
		return err
	}

	defer listener.Close()

	s.logger.Info("listening on TCP", "address", "8383")
	return s.httpServer.Serve(listener)
}

func (s *Server) Shutdown(ctx context.Context) error {
	_ = os.Remove(s.sockPath)
	return s.httpServer.Shutdown(ctx)
}
